const EventEmitter = require('events');
const readline = require('readline');
const MuteStream = require('mute-stream');
const { fromEvent } = require('rxjs');
const ansiEscapes = require('ansi-escapes'); // @5需要使用es module


const options = {
  type: 'list',
  name: 'name',
  message: 'select your name',
  choices: [
    { name: 'madao', value: 'madao' },
    { name: 'zgcf', value: 'zgcf' },
    { name: 'ysx', value: 'ysx' },
  ]
}


class List extends EventEmitter  {
  constructor(options) {
    super();
    this.name = options.name;
    this.message = options.message;
    this.choices = options.choices;
    this.input = process.stdin;
    const ms = new MuteStream();
    ms.pipe(process.stdout); // 静默输出, 也就是不输出
    // this.output = process.stdout;
    this.output = ms;

    this.rl = readline.createInterface({
      input: this.input,
      output: this.output
    });
    // 默认选第一项
    this.selected = 0;

    // 展示的高度(条数)
    this.height = this.choices.length + 1;
    this.keypress$ = fromEvent(this.rl.input, 'keypress').forEach(this.handleKeypress);
    this.haveSelected = false;
  }
  handleKeypress = ([letter, detail]) => {
    // console.log(letter, detail);
    // letter: 按下的具体某个按键, 但特殊的方向键是没有值的，得在detail中判断
    if (detail.name === 'down') {
      this.selected = Math.min(this.selected + 1, this.choices.length -1);
    } else if(detail.name === 'up') {
      this.selected = Math.max(this.selected - 1, 0);
    } else if(detail.name === 'enter') { // mac 叫 return
      this.haveSelected = true;
    }
    this.render();
    if (this.haveSelected) {
      this.close();
      this.emit('exit', this.choices[this.selected]);
    }
  }
  render() {
    this.output.unmute(); // 接触静默
    this.clean();
    // 将content写进输出流，随后再次静默输出(不让用户自己乱输)
    this.output.write(this.getContent());

    // 静默输出
    this.output.mute();
  }

  getContent() {
    // 这里的空格就是 ? 和 message之间的普通空格
    let title = '\x1B[32m?\x1B[39m \x1B[1m' + this.message + '\x1B[22m?\x1B[0m\x1B[0m\x1B[0m\x1B[2m(Use arrow keys)\x1B[22m\n';
    if (this.haveSelected) {
      const name = this.choices[this.selected].name;
      title = '\x1B[32m\x1B[39m \x1B[1m' + this.message + '\x1B[22m：\x1B[0m\x1B[0m\x1B[0m\x1B[2m\x1B[22m' + name + '\x1B[39m\x1B[0m \n';
    } else {
      this.choices.forEach((value, index) => {
        if (this.selected === index) {
          // 最后一个元素不加换行符
          if (index === this.choices.length - 1) {
            // 加了似乎也行
            title += '\x1B[36m> ' + value.name + '\x1B[39m';
          } else {
            title +=  '\x1B[36m> ' + value.name + '\x1B[39m\n';
          }
        } else {
          if (index === this.choices.length - 1) {
            title +=  '  ' + value.name;
          } else {
            title +=  '  ' + value.name + '\n';
          }
        }
      });

      // this.height = this.choices.length + 1;
    }
    return title;
  }
  clean() {
    // 空行数量
    const emptyLines = ansiEscapes.eraseLines(this.height);
    this.output.write(emptyLines);
  }
  close() {
    this.output.unmute();
    this.rl.output.end();
    this.rl.pause();
    this.rl.close();
  }
}

function Prompt(options) {
  return new Promise((resolve, reject) => {
    try {
      const list = new List(options);
      list.render();
      list.on('exit', result => {
        resolve(result);
      });
    } catch(error) {
      reject(error);
    }
  });
}
Prompt(options).then(result => {
  console.log('result', result);
});
